﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;//
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using MotoGame.Estados.Jogo;


namespace MotoGame
{
 /// <summary>
 /// Classe da moto: interação da moto com usuário, representação visual na tela 
 /// </summary>
    class Moto:Sprite
    {

#region Atributos

        SoundEffect ronco;

        animacao andando;
        animacao correndo;
        animacao animacao_atual;

        //jogador
        Jogador jogador;

        //configuracao das teclas
        ConfigTeclas teclas;

        Vector2 gravidade = new Vector2(0, 10);

        //taxa de rotação em radianos
        private float rotacao_taxa = MathHelper.ToRadians(2);

        //angulo máximo de inclinação da moto
        private float rotacao_maxima = MathHelper.ToRadians(60);

#endregion

#region Metodos

        public Moto(ContentManager Content, GameWindow Window, Vector2 posicao, Jogador jogador)
            :base(Content.Load<Texture2D>("moto"))
        {
            this.jogador = jogador;

            this.Window = Window;

            teclas = new ConfigTeclas(jogador);

            textura = Content.Load<Texture2D>("moto");

            this.posicao = posicao;

            ronco = Content.Load<SoundEffect>("Sounds/SoundEffects/engine");

            andando = new animacao();
            andando.quadro_X = 67;
            andando.quadro_Y = 47;
            andando.qtd_quadros = 3;
            andando.quadros_seg = 3;
            andando.Y = 0;

            correndo = new animacao();
            correndo.quadro_X = 67;
            correndo.quadro_Y = 47;
            correndo.qtd_quadros = 3;
            correndo.quadros_seg = 9;
            correndo.Y = 47;

            animacao_atual = andando;

            velocidade = new Vector2(5, 5);

            //deslocamento do ponto de referencia da moto para realizar a rotação correta para empinar a moto
            //ponto o cento da roda trazeira
            pivo = new Vector2(16,34);

        }


        /// <summary>
        /// Update
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
            posicao.Y += gravidade.Y;

            if (Game1.estadoInput.mouse.LeftButton == ButtonState.Pressed)
            {
                posicao.X = Game1.estadoInput.mouse.X;
                posicao.Y = Game1.estadoInput.mouse.Y;
                ronco.Play();
            }

            //if(joystick_atual.Buttons.A), B, X, Y, Left/Right Stick, Left/Right Shoulder, Start, 
            //if(joystick_atual.DPad.Down, Right, Left, Up
            if (Game1.estadoInput.joystick.ThumbSticks.Right.X == 1)
            {
                posicao = Vector2.Zero;
            }

            if (Game1.estadoInput.teclado.IsKeyDown(teclas.direita))
            {
                posicao.X += velocidade.X;
                direita = true;
            }
            if (Game1.estadoInput.teclado.IsKeyDown(teclas.esquerda))
            {
                posicao.X -= velocidade.X;
                direita = false;
            }

            if (Game1.estadoInput.teclado.IsKeyDown(teclas.cima))
            {
                empinar();
            }
            else
            {
                gravidadeRotacao();
            }

            //if (Game1.estadoInput.teclado.IsKeyDown(teclas.baixo))
            //{
            //    posicao.Y += velocidade.Y;
            //}
            if (Game1.estadoInput.teclado.IsKeyDown(teclas.turbo))
            {
                animacao_atual=correndo;
                velocidade.X = 10;
            }
            if (Game1.estadoInput.teclado.IsKeyUp(teclas.turbo))
            {
                animacao_atual = andando;
                velocidade.X = 5;
            }



            if (posicao.X < 0)
            {
                posicao.X = 0;
            }

            colisao = new Rectangle((int)posicao.X, (int)posicao.Y, origem.Width, origem.Height);


            #region manter na tela
            if (posicao.X > Window.ClientBounds.Width - colisao.Width)
            {
                posicao.X = Window.ClientBounds.Width - colisao.Width;
            }

            if (posicao.Y < 0)
            {
                posicao.Y = 0;
            }

            if (posicao.Y > Window.ClientBounds.Height - colisao.Height)
            {
                posicao.Y = Window.ClientBounds.Height - colisao.Height;
            }
            #endregion

        }

        /// <summary>
        /// Empinar moto
        /// </summary>
        private void empinar() 
        {
            rotacao -= rotacao_taxa;
            if (rotacao < -rotacao_maxima) rotacao = -rotacao_maxima;
        }

        /// <summary>
        /// Gravidade sobre a rotação da moto
        /// </summary>
        private void  gravidadeRotacao()
        {
            if (Math.Abs(Math.Round(rotacao,1)) < 0.1) 
            {
                rotacao = 0;
            }
            else
            {
                if (rotacao < 0)
                {
                    rotacao += rotacao_taxa;
                }
                else
                {
                    rotacao -= rotacao_taxa;
                }
            }
        }

        /*
          Namespaces, interfaces e membros de enumeração têm acesso implicitamente “public” e não pode ser modificado;
Tipos (incluindo classes) podem ser “public” ou “internal”, o padrão é “internal”, quase igual a public, visivel dentro do emsmo assembly;
Membros de classes podem ser de todos os tipos, o padrão é “private”;
Membros de estruturas podem ser “public”, “internal” ou “private”, o padrão é “private”;
         */
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            base.Draw(gameTime, spriteBatch, animacao_atual);

            //spriteBatch.Draw(textura, new Rectangle((int)posicao.X, (int)posicao.Y, 67, 47), new Rectangle(0, 0, 67, 47), Color.White);
        }

#endregion

    }

#region Classes Internas

    public class ConfigTeclas
    {
        Keys _cima;
        Keys _baixo;
        Keys _esquerda;
        Keys _direita;
        Keys _turbo;

        public ConfigTeclas(Jogador jogador)
        {
            switch (jogador)
            {
                case Jogador.JOGADOR1:
                    _cima = Keys.Up;
                    _baixo = Keys.Down;
                    _esquerda = Keys.Left;
                    _direita = Keys.Right;
                    _turbo = Keys.RightShift;
                    break;
                case Jogador.JOGADOR2:
                    _cima = Keys.W;
                    _baixo = Keys.S;
                    _esquerda = Keys.A;
                    _direita = Keys.D;
                    _turbo = Keys.LeftShift;
                    break;
            }
        }

        public Keys cima { get { return _cima; } }
        public Keys baixo { get { return _baixo; } }
        public Keys esquerda { get { return _esquerda; } }
        public Keys direita { get { return _direita; } }
        public Keys turbo { get { return _turbo; } }

    }


#endregion

}
